package lumis.portal.serviceinstance.acl;

import lumis.portal.*;
import lumis.portal.authentication.SessionConfig;
import lumis.portal.cache.PortalCache;
import lumis.portal.channel.acl.ChannelPermissions;
import lumis.portal.channel.acl.IChannelAclManager;
import lumis.portal.dao.*;
import lumis.portal.manager.*;
import lumis.portal.service.ServiceConfig;
import lumis.portal.serviceinstance.ServiceInstanceConfig;
import lumis.util.*;
import lumis.util.security.acl.*;

/**
 * Implements the Service Instance ACL Management Interface
 *  
 * @version $Revision: 8949 $ $Date: 2008-03-03 15:23:30 -0300 (Mon, 03 Mar 2008) $
 * @since 4.0.0
 */
public class ServiceInstanceAclManager extends AclManager implements IServiceInstanceAclManager
{
	private PortalCache<ServiceInstancePermissions> serviceInstancePermissionsCache = new PortalCache<ServiceInstancePermissions>("lumis.portal.serviceinstance.acl.ServiceInstancePermissions");
	
	public String add(SessionConfig sessionConfig, ServiceInstanceConfig serviceInstanceConfig, ITransaction transaction) throws ManagerException, PortalException
	{
		IChannelAclManager channelAclManager = ManagerFactory.getChannelAclManager();

		if (!channelAclManager.checkPermission(sessionConfig, serviceInstanceConfig.getChannelId(), ChannelPermissions.MANAGE_SERVICE_INSTANCE, transaction))
			throw new AccessDeniedException();

		// create new acl
		AccessControlList parentAcl = channelAclManager.get(sessionConfig, serviceInstanceConfig.getChannelId(), transaction);
		ServiceInstancePermissions serviceInstancePermissions = getPermissions(sessionConfig, serviceInstanceConfig.getServiceId(), transaction);
		String aclId = super.add(parentAcl, serviceInstancePermissions.getInheritPermissionsMap(), serviceInstancePermissions.getImplies(), transaction);

		serviceInstanceConfig.setAccessControlListId(aclId);
		
		return aclId;
	}

	public AccessControlList get(SessionConfig sessionConfig, String serviceInstanceId, ITransaction transaction) throws ManagerException, PortalException
	{
		return getAclInternal(sessionConfig, serviceInstanceId, transaction);
	}

	public void update(SessionConfig sessionConfig, String serviceInstanceId, AccessControlList acl, ITransaction transaction) throws ManagerException, PortalException
	{
		String serviceId = ManagerFactory.getServiceInstanceManager().get(serviceInstanceId, transaction).getServiceId(); 
		ServiceInstancePermissions serviceInstancePermissions = getPermissions(sessionConfig, serviceId, transaction);
		if (!checkPermission(sessionConfig, serviceInstanceId, serviceInstancePermissions.MANAGE_SERVICE_INSTANCE_SECURITY, transaction))
			throw new AccessDeniedException();

		ServiceInstanceConfig serviceInstanceConfig = ManagerFactory.getServiceInstanceManager().get(serviceInstanceId, transaction);
		String serviceInstanceAcl = serviceInstanceConfig.getAccessControlListId();
		if (!serviceInstanceAcl.equals(acl.getId()))
			throw new PortalException("STR_INVALID_ACCESS_CONTROL_LIST");

		acl.setImpliedPermissions(serviceInstancePermissions.getImplies());
		super.update(acl, transaction);
	}

	public void clearCache(SessionConfig sessionConfig, String serviceInstanceId, ITransaction transaction) throws ManagerException, PortalException
	{
		ServiceInstanceConfig serviceInstanceConfig = ManagerFactory.getServiceInstanceManager().get(serviceInstanceId, transaction);
		if (serviceInstanceConfig != null)
			serviceInstancePermissionsCache.remove(serviceInstanceConfig.getServiceId(), transaction);
	}
	
	public ServiceInstancePermissions getPermissions(SessionConfig sessionConfig, String serviceId, ITransaction transaction) throws ManagerException, PortalException
	{
			ServiceInstancePermissions serviceInstancePermissions = serviceInstancePermissionsCache.get(serviceId);
			if(serviceInstancePermissions == null)
			{
				ServiceConfig serviceConfig = ManagerFactory.getServiceManager().get(sessionConfig, serviceId, transaction);
				serviceInstancePermissions = new ServiceInstancePermissions(serviceConfig);
				serviceInstancePermissionsCache.put(serviceId, serviceInstancePermissions);
			}
			
			return serviceInstancePermissions; 
	}
	
	protected AccessControlList getAclInternal(SessionConfig sessionConfig, String serviceInstanceId, ITransaction transaction) throws ManagerException, PortalException
	{
		ServiceInstanceConfig serviceInstanceConfig = ManagerFactory.getServiceInstanceManager().get(serviceInstanceId, transaction);

		if(serviceInstanceConfig.getAccessControlListId() == null)
			return null;
		
		AccessControlList acl = aclCache.get(serviceInstanceConfig.getAccessControlListId());
		if (acl == null)
		{
			acl = DaoFactory.getAccessControlDao().get(serviceInstanceConfig.getAccessControlListId(), transaction);
			ServiceInstancePermissions serviceInstancePermissions = getPermissions(sessionConfig, serviceInstanceConfig.getServiceId(), transaction);

			if(acl.isInheriting())
			{
				AccessControlList parentChannelAcl = ManagerFactory.getChannelAclManager().get(sessionConfig, serviceInstanceConfig.getChannelId(), transaction);
				acl.inherit(parentChannelAcl, serviceInstancePermissions.getInheritPermissionsMap());
			}
			
			acl.setImpliedPermissions(serviceInstancePermissions.getImplies());

			aclCache.put(acl.getId(), acl);
		}
		return acl;
	}

	protected int getRequiredPermissions() throws PortalException
	{
		return 0;
	}
	
	public void checkRequiredPermissions(AccessControlList acl) throws PortalException
	{
		super.checkRequiredPermissionsInternal(acl);
	}
}
